<?php
/**
 * Created by PhpStorm.
 * User: lihui
 * Date: 3/26/2021
 * Time: 16:36
 */
namespace app\common\model\coin;

use app\common\model\base\A3Mall;
use app\common\model\file\Association;
use app\common\model\order\OrderTake;

use app\common\traits\recordAllRun;
use mall\basic\Users;
use think\facade\Db;

class CoinRuleRunTips extends A3Mall
{

    use recordAllRun;   //使用链表查询处理


    protected $name = "coin_rule_run_tips";

    protected $type = [
    ];


    /**
     * 交易错误类型对应的提示类型
     */
    const TRADE_ERROR_TO_TIP_TYPE_LIST = [
        'BALANCE_ERROR' => 'BUY_FAIL_BALANCE',
        'ACCOUNT_NOT_EXIST' => 'ACCOUNT_NOT_EXIST', //账户不存在
        'SYMBOL_DISABLED' => 'SYMBOL_DISABLED', //禁止交易
        'SYMBOL_DISABLED_FOR_USER' => 'SYMBOL_DISABLED', //禁止交易
        'UNKNOWN' => 'UNKNOWN', //未被定义错误
    ];


    /**
     * 类型列表
     */
    const TYPE_LIST = [
        'FIRST_ORDER'   => 1,   //首单
        'PRICE_MIN'     => 2,   //最低价
        'COVER_AUTO'    => 3,   //自动加仓
        'COVER_MANUAL'  => 4,   //手动加仓
        'PRICE_MAX'     => 5,   //最高价
        'SELL_AUTO'     => 6,   //止盈（自动卖出）
        'SELL_MANUAL'   => 7,   //手动清仓
        'BUY_FAIL_BALANCE' => 8,   //买进失败【余额不足】
        'BUY_SUCCESS'   => 9,   //买进成功
        'SELL_SUCCESS'  => 10,   //卖出成功
        'BUY_CANCELED'  => 11,  //买进撤销
        'SELL_CANCELED' => 12,  //卖出撤销
        'ACCOUNT_NOT_EXIST' => 13,  //账号不存在
        'SYMBOL_DISABLED'   => 14,  //禁止交易
        'UNKNOWN'   => 15,  //未知错误
    ];

    /**
     * 设置消息提示列表
     * @var array
     */
    private $messageList = [ // 类型=>[springf格式化的format,对应参数的键]
        'FIRST_ORDER'   => [
            ['%s/%s 首单买进，金额：%s',['coin_name','unit','amount']],
            ['%s/%s 首单买进，金额：%s，上次保留金额：%s',['coin_name','unit','amount','reserved_amount']],
        ],
        'PRICE_MIN'     => [
            ['%s/%s 达到补仓价格，当前最低价：%s',['coin_name','unit','price_min']],
        ],
        'COVER_AUTO'    => [
            ['%s/%s 加仓买进（第%s手），金额：%s',['coin_name','unit','cover_times','amount']],
        ],
        'COVER_MANUAL'  => [
            ['%s/%s 手动加仓买进，金额：%s',['coin_name','unit','amount']],
        ],
        'PRICE_MAX'     => [
            ['%s/%s 达到止盈价格，当前最高价：%s',['coin_name','unit','price_max']],
        ],
        'SELL_AUTO'     => [
            ['%s/%s 卖出，数量：%s，价格：%s',['coin_name','unit','quantity','unit_price']],
            ['%s/%s 卖出，数量：%s，价格：%s；保留数量：%s，价格：%s',['coin_name','unit','quantity','unit_price','reserved_quantity','reserved_price']],
            ['%s/%s 卖出，数量：%s',['coin_name','unit','quantity']],
            ['%s/%s 卖出，数量：%s；保留数量：%s，价格：%s',['coin_name','unit','quantity','reserved_quantity','reserved_price']],
        ],
        'SELL_MANUAL'   => [
            ['%s/%s 手动清仓，数量：%s，价格：%s',['coin_name','unit','quantity','unit_price']],
            ['%s/%s 手动清仓，数量：%s',['coin_name','unit','quantity']],
        ],
        'BUY_FAIL_BALANCE'      => [
            ['%s/%s 买进失败，余额不足',['coin_name','unit']],
        ],
        'BUY_SUCCESS'   => [
            ['%s/%s 买进成功，数量：%s，价格：%s',['coin_name','unit','field_quantity','field_price']],
            ['%s/%s 买进成功，数量：%s，价格：%s；上次保留数量：%s，价格：%s',['coin_name','unit','field_quantity','field_price','reserved_quantity','reserved_price']],
        ],
        'SELL_SUCCESS'  => [
            ['%s/%s 卖出成功，数量：%s，价格：%s',['coin_name','unit','field_quantity','field_price']],
            ['%s/%s 卖出成功，数量：%s，价格：%s;保留数量：%s，价格：%s',['coin_name','unit','field_quantity','field_price','reserved_quantity','reserved_price']],
        ],
        'BUY_CANCELED'  => [
            ['%s/%s 买进撤销，金额：%s',['coin_name','unit','amount']],
        ],
        'SELL_CANCELED' => [
            ['%s/%s 卖出撤销，数量：%s',['coin_name','unit','quantity']],
        ],
        'ACCOUNT_NOT_EXIST' => [
            ['%s/%s %s失败，火币账户信息错误',['coin_name','unit','tradeTypeStr']],
        ],
        'SYMBOL_DISABLED' => [
            ['%s/%s %s失败，您无法交易该币种',['coin_name','unit','tradeTypeStr']],
        ],
        'UNKNOWN' => [
            ['%s/%s %s失败，交易提交错误',['coin_name','unit','tradeTypeStr']],
        ],
    ];

    // 提示保留的小数点位数
    private $scale = 6;


    /**
     * 请求api错误类型对应的信息提示类型
     * @param string $tradeErrType 错误类型
     * @param int $tradeType    交易类型
     * @return array|null
     */
    static public function getTradeErrTypeToTipType(string $tradeErrType,int $tradeType) {
        if(!array_key_exists($tradeErrType,static::TRADE_ERROR_TO_TIP_TYPE_LIST)) {
            return null;
        }
        return [
            'tradeTypeStr'  => $tradeType == CoinRuleRunTrade::TYPE_BUY?'买进':'卖出',
            'tipsType'  => static::TYPE_LIST[static::TRADE_ERROR_TO_TIP_TYPE_LIST[$tradeErrType]],
        ];
    }




    /** 获取关联所有数据的列表
     * @param array $whereTmp  条件
     * @param array $limit  查询数量
     * @param string $order 排序
     * @param array $fields 查询字段（暂缺）
     * @return array
     */
    public function recordAll($whereTmp = [],$limit = [],$orderTmp = [],$fieldsTmp= []) {

        return $this->recordAllRun([$whereTmp,$limit,$orderTmp,$fieldsTmp],[],[
        ]);
    }

    /**
     * 插入提示信息
     * @param array $tradeDetails 交易详情
     * @param int $type 提示类型 null 为根据tradeDetails自动获取
     */
    public function insertTips(array $tradeDetails,int $type = null) {
        list($type,$typeIndex) = $this->getType($tradeDetails,$type);
        if(!$type) {
            return false;
        }
        if(!$tmp = (new CoinRuleRunTrade())->find($tradeDetails['id'])->toArray()) {
            return false;
        }
        $tradeDetails = array_merge($tradeDetails,$tmp);
        $insertData = [
            'user_id',
            'coin_rule_id',
            'coin_rule_run_id',
            'coin_id',
            'coin_name',
            'unit',
            'cover_times',
            'amount'    => 0,
            'quantity'  => 0,
            'unit_price'    => 0,
        ];
        $tmp = [];
        foreach($insertData as $key=>$val) {
            if(is_integer($key)) {
                $tmp[$val] = $tradeDetails[$val];
            } else {
                $tmp[$key] = array_key_exists($key,$tradeDetails)?$tradeDetails[$key]:$val;
            }
        }
        if(empty($tmp['amount'])) {
            $tmp['amount'] = $tradeDetails['field_amount'];
        }
        if(empty($tmp['quantity'])) {
            $tmp['quantity'] = $tradeDetails['field_quantity'];
        }
        if(empty($tmp['unit_price'])) {
            $tmp['unit_price'] = $tradeDetails['field_price'];
        }
        $tmp['type'] = $type;
        $insertData = array_merge($tmp,[
            'message'   => $this->sprintfMessage(array_merge($tradeDetails,$tmp),$typeIndex),
            'read_time'  => 0,
            'create_time'  => time(),
            'update_time'  => time(),
        ]);
        $insertData['id'] = $this->insertGetId($insertData);
        // 返回添加详情
        return $insertData;


    }


    /**
     * 获取类型
     * @param array $tradeDetails
     * @param int|null $type
     * @return int
     */
    private function getType(array $tradeDetails,int $type = null) {
        $index = 0;
        if(!$type) {
            switch ($tradeDetails['status']) {
                case CoinRuleRunTrade::STATUS_FILLED:   //全部撮合完成
                case CoinRuleRunTrade::STATUS_PARTIAL_CANCELED: //撤销，但部分撮合完成
                    $type = $tradeDetails['type'] == CoinRuleRunTrade::TYPE_BUY?static::TYPE_LIST['BUY_SUCCESS']:static::TYPE_LIST['SELL_SUCCESS'];
                    break;
                case CoinRuleRunTrade::STATUS_CANCELED: //取消，撮合失败
                    $type = $tradeDetails['type'] == CoinRuleRunTrade::TYPE_BUY?static::TYPE_LIST['BUY_CANCELED']:static::TYPE_LIST['SELL_CANCELED'];
                    break;
                case CoinRuleRunTrade::STATUS_APPLY:    //申请提示
                    if($tradeDetails['cover_times'] < 0) {
                        //手动补仓 OR 手动清仓
                        $type = $tradeDetails['type'] == CoinRuleRunTrade::TYPE_BUY?static::TYPE_LIST['COVER_MANUAL']:static::TYPE_LIST['SELL_MANUAL'];
                    }  else if($tradeDetails['cover_times']  > 0) {
                        //自动补仓
                        $type = static::TYPE_LIST['COVER_AUTO'];
                    } else {
                        //自动首单 OR 自动清仓
                        $type = $tradeDetails['type'] == CoinRuleRunTrade::TYPE_BUY?static::TYPE_LIST['FIRST_ORDER']:static::TYPE_LIST['SELL_AUTO'];
                    }
                    break;
                case CoinRuleRunTrade::STATUS_FAIL: //买卖失败【主要买进金额不足】
                    if($tradeDetails['type'] == CoinRuleRunTrade::TYPE_BUY) {
                        $type = static::TYPE_LIST['BUY_FAIL'];
                    }
            }
        }

        /***************** 判断并获取类型对应的索引 *************************/
        switch ($type) {
            case static::TYPE_LIST['FIRST_ORDER']:
                if(bccomp($tradeDetails['reserved_amount'],0,$this->scale) ==1) {
                    $index = 1;
                }
                break;
            case static::TYPE_LIST['BUY_SUCCESS']:
                if(bccomp($tradeDetails['reserved_quantity'],0,$this->scale) ==1) {
                    $index = 1;
                }
                break;
            case static::TYPE_LIST['SELL_MANUAL']:  // 手动清仓处理
                if(bccomp($tradeDetails['unit_price'],0,30) != 1) {
                    $index = 1; // 无价格显示
                }
                break;
            case static::TYPE_LIST['SELL_AUTO']:
                if(bccomp($tradeDetails['unit_price'],0,30) == 1) {
                    if(bccomp($tradeDetails['reserved_quantity'],0,$this->scale) ==1) {
                        $index = 1;
                    }
                } else {
                    if(bccomp($tradeDetails['reserved_quantity'],0,$this->scale) ==1) {
                        $index = 3;
                    } else {
                        $index = 2;
                    }
                }
                break;
            case static::TYPE_LIST['SELL_SUCCESS']:
                if(bccomp($tradeDetails['reserved_quantity'],0,$this->scale) ==1) {
                    $index = 1;
                }
                BREAK;
        }
        /*************** END 判断并获取类型对应的索引 ***********************/
        return [$type,$index];
    }

    /**
     * 格式化msg提示内容
     * @param array $details
     * @param int $type
     */
    private function sprintfMessage(array $details,$typeIndex) {
        list($format,$params) = $this->messageList[array_search($details['type'],static::TYPE_LIST)][$typeIndex];
        foreach($params as &$value) {
            $value = $details[$value];
            if(preg_match('/^[0-9]+(\.[0-9]+)?$/',$value)) {
                $value = rtrim(rtrim(bcadd($value,0,$this->scale),0),'.');
            }
        }
        array_unshift($params,$format);
        return call_user_func_array('sprintf',$params);
    }

    public function getCreateTimeAttr($value,$data)
    {
        return date("Y-m-d H:i:s",$data['create_time']);
    }




}
